home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / games / sokosrc.zoo / play.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  10KB  |  293 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <curses.h>
  4. #include "sokoban.h"
  5.  
  6. /* defining the types of move */
  7. #define MOVE           1
  8. #define PUSH           2
  9. #define SAVE           3
  10. #define UNSAVE                 4
  11. #define STOREMOVE      5
  12. #define STOREPUSH      6
  13.  
  14. /* defines for control characters */
  15. #define CNTL_L         '\014'
  16. #define CNTL_K         '\013'
  17. #define CNTL_H         '\010'
  18. #define CNTL_J         '\012'
  19. #define CNTL_R         '\022'
  20. #define CNTL_U         '\025'
  21.  
  22. extern char map[MAXROW+1][MAXCOL+1];
  23. extern short rows, cols, level, moves, pushes, savepack, packets;
  24. extern short scorelevel, scoremoves, scorepushes;
  25. extern POS ppos;
  26.  
  27. POS tpos1, tpos2;      /* test positions: 1/2 pos. over/under/left/right */
  28. #if 0
  29. POS    lastppos,          /* the last player position (for undo) */
  30.     lasttpos1, lasttpos2; /* last test positions (for undo) */
  31. char lppc, ltp1c, ltp2c;  /* the char for these positions (for undo) */
  32. short lastaction;
  33. #endif
  34. short action;
  35.  
  36. soko_state state[2000];        /* All the moves user has made */
  37. int state_num = 0;            /* Last (+1) action in state */
  38.  
  39. int tmp_statenum;            /* State number of temporary save */
  40. char tmp_map[MAXROW+1][MAXCOL+1];
  41. short tmp_pushes, tmp_moves, tmp_savepack;
  42. POS tmp_ppos;
  43.  
  44. #if ATARIST
  45. char shifted[128], unshifted[128];
  46. #endif
  47.  
  48. int play() {
  49.  
  50.    short c;
  51.    short ret;
  52.    short testmove();
  53.    short undolock = 1;         /* locked for undo */
  54.  
  55. #if ATARIST            /* Mess up keyboard to make cursor keys work */
  56. KEY_TABLES *kbt;
  57. KEY_TABLES old_kbt;
  58. int i;
  59.  
  60.     kbt = Keytbl(-1, -1, -1);
  61.     old_kbt = *kbt;
  62.  
  63.     for (i = 0; i < 128; i++) {
  64.         unshifted[i] = kbt->unshifted[i];
  65.         shifted[i] = kbt->shifted[i];
  66.     }
  67.  
  68.     unshifted[0x48] = 'k';    /* Up */
  69.     unshifted[0x50] = 'j';    /* Down */
  70.     unshifted[0x4b] = 'h';    /* Left */
  71.     unshifted[0x4d] = 'l';    /* Right */
  72.     unshifted[0x61] = 'u';    /* Undo */
  73.     unshifted[0x62] = '?';    /* Help */
  74.  
  75.     shifted[0x48] = '\013';    /* Up ^K */
  76.     shifted[0x50] = '\012';    /* Down ^J */
  77.     shifted[0x4b] = '\010';    /* Left ^H */
  78.     shifted[0x4d] = '\014';    /* Right ^L */
  79.     shifted[0x61] = 'q';    /* Undo */
  80.  
  81.     Keytbl(unshifted, shifted, -1);
  82. #endif
  83.  
  84.    showscreen();
  85.    tmpsave();
  86.    ret = 0;
  87.    while( ret == 0) {
  88.       switch( (c = get_char())) {
  89.         case 'q':    /* quit the game                                  */
  90.                 ret = E_ENDGAME;
  91.                 break;
  92.         case 's':    /* save the games                                 */
  93.                      if( (ret = savegame()) == 0)
  94.                         ret = E_SAVED;
  95.                      break;
  96.         case '?':    /* show the help file                             */
  97.                      showhelp();
  98.                      showscreen();
  99.                      break;
  100.         case CNTL_R: /* refresh the screen                             */
  101.                      clear();
  102.                      showscreen();
  103.                      break;
  104.         case 'c':    /* temporary save                                 */
  105.                      tmpsave();
  106.                      break;
  107.         case CNTL_U: /* reset to temporary save                        */
  108.                      tmpreset();
  109.                      undolock = 1;
  110.                      showscreen();
  111.                      break;
  112.         case 'U':    /* undo this level                                */
  113.                      moves = pushes = 0;
  114.                      if( (ret = readscreen()) == 0) {
  115.                         showscreen();
  116.                         undolock = 1;
  117.                      }
  118.                      break;
  119.         case 'u':    /* undo last move                                 */
  120.                      if(state_num > 0) {
  121.                         undomove();
  122.                         undolock = 0;    /*1*/
  123.                      }
  124.                      break;
  125.         case 'k':    /* up                                             */
  126.         case 'K':    /* run up                                         */
  127.         case CNTL_K: /* run up, stop before object                     */
  128.         case 'j':    /* down                                           */
  129.         case 'J':    /* run down                                       */
  130.         case CNTL_J: /* run down, stop before object                   */
  131.         case 'l':    /* right                                          */
  132.         case 'L':    /* run right                                      */
  133.         case CNTL_L: /* run right, stop before object                  */
  134.         case 'h':    /* left                                           */
  135.         case 'H':    /* run left                                       */
  136.         case CNTL_H: /* run left, stop before object                   */
  137.                      do {
  138.                         if( (action = testmove( c)) != 0) {
  139.                         soko_state *s;
  140.                             s = &state[state_num];
  141.  
  142.                             s->action = action;
  143.                             s->ppos = ppos;
  144.                             s->lppc = map[ppos.x][ppos.y];
  145.                             s->tpos1 = tpos1;
  146.                             s->ltp1c = map[tpos1.x][tpos1.y];
  147.                             s->tpos2 = tpos2;
  148.                             s->ltp2c = map[tpos2.x][tpos2.y];
  149.                            domove( s->action);
  150.                            undolock = 0;
  151.                            state_num++;
  152.                         }
  153.                      } while( (action != 0) && (! islower( c))
  154.                              && (packets != savepack));
  155.                      break;
  156.         default:     helpmessage(); break;
  157.       }
  158.       if( (ret == 0) && (packets == savepack)) {
  159.         scorelevel = level;
  160.         scoremoves = moves;
  161.         scorepushes = pushes;
  162.         break;
  163.       }
  164.    }
  165. #if ATARIST
  166.     kbt = Keytbl(-1, -1, -1);
  167.     kbt->unshifted = old_kbt.unshifted;
  168.     kbt->shifted = old_kbt.shifted;
  169. /*    Keytbl(old_kbt.unshifted, old_kbt.shifted, old_kbt.capslock);*/
  170. #endif
  171.     return ret;
  172. }
  173.  
  174. short testmove( action)
  175. short action;
  176. {
  177.    short ret;
  178.    char tc;
  179.    short stop_at_object;
  180.  
  181.    if( (stop_at_object = iscntrl( action))) action = action + 'A' - 1;
  182.    action = (isupper(action) ? tolower( action) : action);
  183.    if( (action == 'k') || (action == 'j')) {
  184.       tpos1.x = (action == 'k') ? ppos.x-1 : ppos.x+1;
  185.       tpos2.x = (action == 'k') ? ppos.x-2 : ppos.x+2;
  186.       tpos1.y = tpos2.y = ppos.y;
  187.    }
  188.    else {
  189.       tpos1.y = (action == 'h') ? ppos.y-1 : ppos.y+1;
  190.       tpos2.y = (action == 'h') ? ppos.y-2 : ppos.y+2;
  191.       tpos1.x = tpos2.x = ppos.x;
  192.    }
  193.    tc = map[tpos1.x][tpos1.y];
  194.    switch( tc) {
  195.       case C_PACKET:
  196.       case C_SAVE:   if( ! stop_at_object) {
  197.                        if( map[tpos2.x][tpos2.y] == C_GROUND)
  198.                           ret = (tc == C_SAVE) ? UNSAVE : PUSH;
  199.                         else if( map[tpos2.x][tpos2.y] == C_STORE)
  200.                           ret = (tc == C_SAVE) ? STOREPUSH : SAVE;
  201.                        else ret = 0;
  202.                     }
  203.                     else ret = 0;                                      break;
  204.       case C_GROUND: ret = MOVE;                                       break;
  205.       case C_STORE:  ret = STOREMOVE;                                  break;
  206.       default:       ret = 0;                                          break;
  207.    }
  208.    return( ret);
  209. }
  210.  
  211. domove( moveaction)
  212. short moveaction;
  213. {
  214.    map[ppos.x][ppos.y] = (map[ppos.x][ppos.y] == C_PLAYER)
  215.                               ? C_GROUND
  216.                               : C_STORE;
  217.    switch( moveaction) {
  218.       case MOVE:      map[tpos1.x][tpos1.y] = C_PLAYER;                break;
  219.       case STOREMOVE: map[tpos1.x][tpos1.y] = C_PLAYERSTORE;           break;
  220.       case PUSH:      map[tpos2.x][tpos2.y] = map[tpos1.x][tpos1.y];
  221.                      map[tpos1.x][tpos1.y] = C_PLAYER;
  222.                      pushes++;                                         break;
  223.       case UNSAVE:    map[tpos2.x][tpos2.y] = C_PACKET;
  224.                      map[tpos1.x][tpos1.y] = C_PLAYERSTORE;
  225.                      pushes++; savepack--;                             break;
  226.       case SAVE:      map[tpos2.x][tpos2.y] = C_SAVE;
  227.                      map[tpos1.x][tpos1.y] = C_PLAYER;
  228.